import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
import QQConnect from 'qq-connect'
import { v4 as uuidv4 } from 'uuid'
import WechatOAuth from 'wechat-oauth'
import WeiboOAuth from 'weibo-oauth'
import { authConfig } from '../../config/auth'
import { User } from '../../models/User'
import { AppError } from '../../utils/AppError'
import { RedisService } from '../redis/RedisService'

export class AuthService {
  private redis: RedisService
  private wechatClient: any
  private qqClient: any
  private weiboClient: any

  constructor() {
    this.redis = new RedisService()

    // 初始化微信OAuth
    this.wechatClient = new WechatOAuth(authConfig.wechat.appId, authConfig.wechat.appSecret)

    // 初始化QQ OAuth
    this.qqClient = new QQConnect({
      appID: authConfig.qq.appId,
      appKey: authConfig.qq.appKey,
      redirect_uri: authConfig.qq.redirectUri,
    })

    // 初始化微博OAuth
    this.weiboClient = new WeiboOAuth(authConfig.weibo.appKey, authConfig.weibo.appSecret)
  }

  // 手机号登录
  async loginByPhone(phone: string, code: string) {
    // 验证验证码
    const validCode = await this.redis.get(`sms:login:${phone}`)
    if (!validCode || code !== validCode) {
      throw new AppError(400, '验证码错误或已过期')
    }

    // 查找或创建用户
    let user = await User.findOne({ phone })
    if (!user) {
      user = await User.create({
        username: `user_${uuidv4().substr(0, 8)}`,
        nickname: `用户${phone.substr(-4)}`,
        phone,
        password: await bcrypt.hash(uuidv4(), 10),
      })
    }

    return this.generateAuthResponse(user)
  }

  // 微信登录
  async loginByWechat(code: string) {
    // 获取微信用户信息
    const token = await this.wechatClient.getAccessToken(code)
    const openid = token.data.openid
    const userInfo = await this.wechatClient.getUser(openid)

    // 查找或创建用户
    let user = await User.findOne({ 'oauth.wechat.openid': openid })
    if (!user) {
      user = await User.create({
        username: `wx_${openid.substr(-8)}`,
        nickname: userInfo.nickname,
        avatar: userInfo.headimgurl,
        oauth: {
          wechat: {
            openid,
            unionid: userInfo.unionid,
          },
        },
      })
    }

    return this.generateAuthResponse(user)
  }

  // QQ登录
  async loginByQQ(code: string) {
    const token = await this.qqClient.getAccessToken(code)
    const openid = await this.qqClient.getOpenId(token)
    const userInfo = await this.qqClient.getUserInfo(token, openid)

    let user = await User.findOne({ 'oauth.qq.openid': openid })
    if (!user) {
      user = await User.create({
        username: `qq_${openid.substr(-8)}`,
        nickname: userInfo.nickname,
        avatar: userInfo.figureurl_qq_2 || userInfo.figureurl_qq_1,
        oauth: {
          qq: { openid },
        },
      })
    }

    return this.generateAuthResponse(user)
  }

  // 发送登录验证码
  async sendLoginCode(phone: string) {
    // 检查发送频率
    const lastSend = await this.redis.get(`sms:limit:${phone}`)
    if (lastSend) {
      throw new AppError(429, '发送太频繁，请稍后再试')
    }

    // 生成验证码
    const code = Math.random().toString().substr(2, 6)

    // 调用短信服务发送验证码
    try {
      await this.sendSms(phone, code)

      // 保存验证码和限制发送频率
      const multi = this.redis.multi()
      multi.setex(`sms:login:${phone}`, authConfig.sms.expireTime, code)
      multi.setex(`sms:limit:${phone}`, authConfig.sms.limitTime, '1')
      await multi.exec()

      return { success: true }
    } catch (error) {
      throw new AppError(500, '短信发送失败')
    }
  }

  // 刷新Token
  async refreshToken(refreshToken: string) {
    try {
      const decoded = jwt.verify(refreshToken, authConfig.jwt.refreshSecret) as any
      const user = await User.findById(decoded.id)

      if (!user || user.status !== 'active') {
        throw new AppError(401, '无效的刷新令牌')
      }

      return this.generateAuthResponse(user)
    } catch (error) {
      throw new AppError(401, '无效的刷新令牌')
    }
  }

  // 生成认证响应
  private generateAuthResponse(user: any) {
    const accessToken = jwt.sign({ id: user._id }, authConfig.jwt.accessSecret, {
      expiresIn: authConfig.jwt.accessExpire,
    })

    const refreshToken = jwt.sign({ id: user._id }, authConfig.jwt.refreshSecret, {
      expiresIn: authConfig.jwt.refreshExpire,
    })

    // 更新登录信息
    user.lastLoginTime = new Date()
    user.save()

    return {
      user: {
        id: user._id,
        username: user.username,
        nickname: user.nickname,
        avatar: user.avatar,
        level: user.level,
        vipLevel: user.vipLevel,
      },
      tokens: {
        accessToken,
        refreshToken,
        expiresIn: authConfig.jwt.accessExpire,
      },
    }
  }

  // 发送短信
  private async sendSms(phone: string, code: string) {
    // 根据配置选择短信服务商
    if (authConfig.sms.provider === 'aliyun') {
      // 阿里云短信
      // 实现代码...
    } else if (authConfig.sms.provider === 'tencent') {
      // 腾讯云短信
      // 实现代码...
    }
  }
}
